#!/usr/bin/env bash

# update_device - format physical and virtual disk signatures/offsets
#                    used by device entries such as 11000001 and 21000001
#
# Copyright (C) 2024 Joseph P. Zeller
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

endian () {
v=$1
i=${#v}

while [ $i -gt 0 ]
do
    i=$[$i-2]
    echo -n ${v:$i:2}
done
echo
}

guid_bytes () {
guidstr="$1"
IFS='-'

   read -a strarr <<< "$guidstr"

   guidbytes=$(endian ${strarr[0]})
   guidbytes+=$(endian ${strarr[1]})
   guidbytes+=$(endian ${strarr[2]})
   guidbytes+=${strarr[3]}
   guidbytes+=${strarr[4]}
   
   echo $guidbytes
}

blksize () {
sectsz=$(diskutil info $1 | grep "Device Block Size:" | awk '{print $4}')
echo $sectsz
}

part="$1"
echo "part: $part" 1>&2
disk=$(printf $part | sed 's/s[0-9]*$//')
echo "disk: $disk" 1>&2
scheme=$(diskutil info $disk | grep "Content (IOContent):" | awk '{print $3}')
echo "scheme: $scheme" 1>&2
if [[ "$scheme" == "GUID_partition_scheme" ]]; then
    if [[ ! -z $(echo "$mypassword" | sudo -S fdisk "$disk" | grep -E '2:|3:|4:' | grep -v unused) ]]; then
       scheme="FDisk_partition_scheme" #Use fdisk option for GPT disk with hybrid MBR.
       echo "scheme: $scheme" 1>&2
    fi
fi

if   [[ "$scheme" == "GUID_partition_scheme" ]]; then
     sectsize=$(blksize $disk)
     echo "sectsize: $sectsize" 1>&2
     diskbytes=$(sudo -S xxd -u -p -s $(($sectsize + 56)) -l 16 $disk | sed 's/.\{2\}/&,/g;s/,$//')
     echo "diskbytes: $diskbytes" 1>&2
     partguid=$(diskutil info $part | grep "Partition UUID:" | awk '{print $5}')
     echo "partguid: $partguid" 1>&2
     partbytes=$(printf "%s" $(guid_bytes $partguid) | sed 's/.\{2\}/&,/g;s/,$//')
     echo "partbytes: $partbytes" 1>&2
     schemebyte="00"
elif [[ "$scheme" == "FDisk_partition_scheme" ]]; then
      disksig=$(sudo -S xxd -u -p -s 440 -l 4 $disk)
      echo "disksig: $disksig" 1>&2
      partoffset=$(diskutil info $part | grep "Partition Offset:" | awk '{print $3}')
      if [[ -z $partoffset ]]; then
         hidsect=$(sudo -S fdisk $disk | tail -n +6 | awk -v partnum=${part##*s} 'FNR == partnum {print $11}')
         sectsize=$(blksize $disk)
         partoffset=$(($sectsize * $hidsect))
      fi
      echo "partoffset: $partoffset" 1>&2
      diskbytes=$(printf "%s" $(printf "%x%024x" "0x$disksig") | sed 's/.\{2\}/&,/g;s/,$//')
      partbytes=$(printf "%s" $(endian $(printf "%032x" "$partoffset")) | sed 's/.\{2\}/&,/g;s/,$//')
      schemebyte="01"
      echo "diskbytes: $diskbytes" 1>&2
      echo "partbytes: $partbytes" 1>&2
fi
    printf "hex:3:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,06,00,00,00,00,00,00,00,48,00,00,00,00,00,00,00,$partbytes,00,00,00,00,$schemebyte,00,00,00,$diskbytes,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00\n"


